package model.mediators;

import java.util.List;

import model.entity.Entity;
import model.map.GameMap;
import model.map.MapPoint;

public class ModelMovementMediator extends MapMediator{
	
	public static void checkedMoveNorth(Entity mover) {
		
		checkedMove(mover, MapPoint.NORTH);		
	}
	
	public static void checkedMoveNE(Entity mover) {
		checkedMove(mover, MapPoint.NORTHEAST);	
	}
	public static void checkedMoveNW(Entity mover) {
		checkedMove(mover, MapPoint.NORTHWEST);	
	}
	public static void checkedMoveSouth(Entity mover) {
		checkedMove(mover, MapPoint.SOUTH);
	}
	public static void checkedMoveSE(Entity mover) {
		checkedMove(mover, MapPoint.SOUTHEAST);
	}
	public static void checkedMoveSW(Entity mover) {
		checkedMove(mover, MapPoint.SOUTHWEST);
	}
	
	private static void checkedMove(Entity mover, MapPoint direction) {
		MapPoint pointToMove = MapPoint.addPoints(mover.getLocation(), direction);
		finalMove(mover, pointToMove);		
	}
	
	private static void finalMove(Entity mover, MapPoint pointToMove) {
		MapPoint previousPoint = mover.getLocation();
		GameMap gameMap = MapMediator.getMap();
		List<Entity> entityList = gameMap.getEntitiesOnTile(pointToMove);
		if (entityList.isEmpty()) {
			if (gameMap.getObstaclesOnTile(pointToMove).isEmpty() && gameMap.getTerrain(pointToMove).isPassable(mover.getMovementType())) {
				gameMap.removeEntityFromTile(mover, previousPoint);
				gameMap.addEntityToTile(mover, pointToMove);
				mover.setLocation(pointToMove);
			}
			else {
				return;
			}
		}
		else {
			mover.interactWith(entityList);
				
		}
	}
	public static void relativeTeleport(Entity mover, MapPoint displacement) {
		MapPoint newLocation = MapPoint.addPoints(mover.getLocation(), displacement);
		finalMove(mover, newLocation);
	}
	public static void absoluteTeleport(Entity mover, MapPoint destinationPoint) {
		finalMove(mover, destinationPoint);
	}
	
	public static void delayByTerrain(Entity mover) {
		mover.disable(MapMediator.getMap().getTerrain(mover.getLocation()).getSpeed(mover.getMovementType()));
		
	}
	
	public static void delay(Entity mover, int cycles) {
		mover.disable(cycles);
	}
	public static void pushMoveNorth(Entity mover, int cycles) {
		pushMove(mover, cycles, MapPoint.NORTH);	
	}
	
	public static void pushMoveNE(Entity mover, int cycles) {
		pushMove(mover, cycles, MapPoint.NORTHEAST);
		
	}
	public static void pushMoveNW(Entity mover, int cycles) {
		pushMove(mover, cycles, MapPoint.NORTHWEST);
		
	}
	public static void pushMoveSouth(Entity mover, int cycles) {
		pushMove(mover, cycles, MapPoint.SOUTH);
		
	}
	public static void pushMoveSE(Entity mover, int cycles) {
		pushMove(mover, cycles, MapPoint.SOUTHEAST);
		
	}
	public static void pushMoveSW(Entity mover, int cycles) {
		pushMove(mover, cycles, MapPoint.SOUTHWEST);
		
	}

	private static void pushMove(Entity mover, int cycles, MapPoint direction) {
		delay(mover, cycles);
		checkedMove(mover, direction);
	}
	
	public static void attemptToMoveNorth(Entity mover) {
		attemptToMove(mover, MapPoint.NORTH);
	}
	public static void attemptToMoveNE(Entity mover) {
		attemptToMove(mover, MapPoint.NORTHEAST);
	}
	public static void attemptToMoveNW(Entity mover) {
		attemptToMove(mover, MapPoint.NORTHWEST);
	}
	
	public static void attemptToMoveSouth(Entity mover) {
		attemptToMove(mover, MapPoint.SOUTH);
	}
	
	public static void attemptToMoveSE(Entity mover) {
		attemptToMove(mover, MapPoint.SOUTHEAST);
	}
	
	public static void attemptToMoveSW(Entity mover) {	
		attemptToMove(mover, MapPoint.SOUTHWEST);
	}
	private static void attemptToMove(Entity mover, MapPoint direction) {
		delayByTerrain(mover);
		checkedMove(mover, direction);
	}

}
